package com.atguigu.lease.web.admin.service.impl;

import com.atguigu.lease.common.exception.LeaseException;
import com.atguigu.lease.common.result.Result;
import com.atguigu.lease.common.result.ResultCodeEnum;
import com.atguigu.lease.module.entity.*;
import com.atguigu.lease.module.enums.ItemType;
import com.atguigu.lease.web.admin.mapper.ApartmentInfoMapper;
import com.atguigu.lease.web.admin.service.*;
import com.atguigu.lease.web.admin.vo.apartment.ApartmentDetailVo;
import com.atguigu.lease.web.admin.vo.apartment.ApartmentItemVo;
import com.atguigu.lease.web.admin.vo.apartment.ApartmentQueryVo;
import com.atguigu.lease.web.admin.vo.apartment.ApartmentSubmitVo;
import com.atguigu.lease.web.admin.vo.graph.GraphVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class ApartmentInfoServiceImpl extends ServiceImpl<ApartmentInfoMapper, ApartmentInfo> implements ApartmentInfoService {

    @Autowired
    private ApartmentInfoMapper apartmentInfoMapper;

    @Autowired
    private ApartmentFacilityService apartmentFacilityService;

    @Autowired
    private ApartmentLabelService apartmentLabelService;

    @Autowired
    private ApartmentFeeValueService apartmentFeeValueService;

    @Autowired
    private GraphInfoService graphInfoService;

    @Autowired
    private RoomInfoService roomInfoService;






    @Override
     public void saveOrUpdateApartment(@RequestBody ApartmentSubmitVo apartmentSubmitVo) {
        Long apartmentId0 = apartmentSubmitVo.getId();

        Boolean updateFlag = apartmentId0 != null && apartmentId0 != 0;

        //1.保存或更新自身信息


        if (updateFlag) {
            //如果能查到id 说明是更新操作 更新之前需要删除之前的关系信息 多对多表中删除的都是中间关系表
            //1.删除跟配套的关系信息
            apartmentFacilityService.remove(new LambdaQueryWrapper<ApartmentFacility>().eq(ApartmentFacility::getApartmentId, apartmentId0));
            //2.删除跟标签的关系信息
            apartmentLabelService.remove(new LambdaQueryWrapper<ApartmentLabel>().eq(ApartmentLabel::getApartmentId, apartmentId0));
            //3.删除跟杂费有关的信息
            apartmentFeeValueService.remove(new LambdaQueryWrapper<ApartmentFeeValue>().eq(ApartmentFeeValue::getApartmentId, apartmentId0));
            //4.删除跟图片有关信息
            graphInfoService.remove(new LambdaQueryWrapper<GraphInfo>().eq(GraphInfo::getItemId, apartmentId0).eq(GraphInfo::getItemType, ItemType.APARTMENT));
        }
        ;


        //2.保存公寓的关系信息 通过原生的saveOrUpdate 只能更新或保存基本属性 对关系属性不起作用
        super.saveOrUpdate(apartmentSubmitVo);//执行原生的saveOrUpdate 可以保存apartmentInfo基本信息到数据库
        //执行原生saveOrUpdate后会有id自增列 可以获取
        Long apartmentId = apartmentSubmitVo.getId();
        List<GraphInfo> graphInfoList = new ArrayList<>();

        //2.1 保存和配套的关系信息
        apartmentSubmitVo.getFacilityInfoIds().stream().map(facilityInfoId -> {
            return new ApartmentFacility(apartmentId, facilityInfoId);
        }).forEach(apartmentFacilityService::saveOrUpdate);
        //2.2 保存和标签的关系信息
        apartmentSubmitVo.getLabelIds().stream().map(labelInfoId -> {
            return new ApartmentLabel(apartmentId, labelInfoId);
        }).forEach(apartmentLabelService::saveOrUpdate);
        //2.3 保存和杂费的关系信息 【为啥是跟feeValue建立关系呢】
        apartmentSubmitVo.getFeeValueIds().stream().map(feeValueId -> {
            return new ApartmentFeeValue(apartmentId, feeValueId);
        }).forEach(apartmentFeeValueService::saveOrUpdate);
        //2.4 保存和图片的关系信息（一对多）
        apartmentSubmitVo.getGraphVoList().forEach(graphVo -> {
            GraphInfo graphInfo = new GraphInfo();
            BeanUtils.copyProperties(graphVo, graphInfo);
            graphInfo.setItemId(apartmentId);
            graphInfo.setItemType(ItemType.APARTMENT);
            graphInfoList.add(graphInfo);
        });
        graphInfoService.saveOrUpdateBatch(graphInfoList);



    };

    @Override
    public void pageApartmentItemByQuery(IPage<ApartmentItemVo> page, ApartmentQueryVo apartmentQueryVo) {
        apartmentInfoMapper.pageApartmentItemByQuery(page, apartmentQueryVo);
    }

    @Override
    public ApartmentDetailVo getApartmentDetail(Long id) {
        //在业务方法里面查找公寓基本信息及关系信息
        //1.获取apartmentInfo基本信息
        ApartmentInfo apartmentInfo = this.getById(id);
        if(apartmentInfo==null){
            return null;
        }
        //2.获取公寓跟配套的关系信息 不仅获取配套的id 还有其他facility的具体信息 所以不能用原生api getById 需要手动实现
        List<FacilityInfo> facilityInfoList = apartmentFacilityService.getApartmentFacilityListByApartmentId(id);
        //3.获取公寓跟标签的关系信息
        List<LabelInfo> labelInfoList = apartmentLabelService.getApartmentLabelListByApartmentId(id);
        //4.获取公寓跟杂费的关系信息
        List<FeeValue> feeValueList = apartmentFeeValueService.getApartmentFeeValueListByApartmentId(id);
        //5.获取公寓跟图片的关系信息
        //直接用graphInfo也可以实现 但是模板用的是graphVo
        List<GraphInfo> graphInfoList = graphInfoService.list(new LambdaQueryWrapper<GraphInfo>().eq(GraphInfo::getItemType,ItemType.APARTMENT).eq(GraphInfo::getItemId,id));
        ApartmentDetailVo apartmentDetailVo = new ApartmentDetailVo();
        BeanUtils.copyProperties(apartmentInfo,apartmentDetailVo);
        apartmentDetailVo.setFacilityInfoList(facilityInfoList);
        apartmentDetailVo.setLabelInfoList(labelInfoList);
        apartmentDetailVo.setFeeValueList(feeValueList);
        //apartmentDetailVo.setGraphInfoList(graphInfoList.stream().collect(Collectors.toList()));
        apartmentDetailVo.setGraphVoList(graphInfoList.stream().map(graphInfo -> GraphVo.builder().name(graphInfo.getName()).url(graphInfo.getUrl()).build()).collect(Collectors.toList()));

        return apartmentDetailVo;


    }

    @Override
    public void removeApartmentById(Long id) {
        if(roomInfoService.count(new LambdaQueryWrapper<RoomInfo>().eq(RoomInfo::getApartmentId,id))>0){
            throw new LeaseException(ResultCodeEnum.DELETE_ERROR);
        }

        //1.删除公寓本身的信息
        super.removeById(id);
        //2.删除跟配套的关系信息
        apartmentFacilityService.remove(new LambdaQueryWrapper<ApartmentFacility>().eq(ApartmentFacility::getApartmentId,id));
        //3.删除跟标签的关系信息
        apartmentLabelService.remove(new LambdaQueryWrapper<ApartmentLabel>().eq(ApartmentLabel::getApartmentId,id));
        //4.删除跟杂费的关系信息
        apartmentFeeValueService.remove(new LambdaQueryWrapper<ApartmentFeeValue>().eq(ApartmentFeeValue::getApartmentId,id));
        //5.删除图片
        graphInfoService.remove(new LambdaQueryWrapper<GraphInfo>().eq(GraphInfo::getItemType,ItemType.APARTMENT).eq(GraphInfo::getItemId,id));

    }
}


